home *** CD-ROM | disk | FTP | other *** search
Text File | 1998-06-19 | 7.2 KB | 251 lines | [TEXT/CWIE] |
- /*
- Problem 10 - Interpreter
-
- Write an interpreter for this simple 32-bit integer language with 26 registers
- labeled A-Z.
-
- type RegisterArray = array[0..25] of SInt32;
-
- procedure Interpret( source: Handle; var result: RegisterArray );
-
- source consists of a number of lines of the form:
-
- [<label>:][<tab><instruction><tab><operand-list>]<cr>
-
- <label> is a sequence of at least two alphanumerics (0-9a-zA-Z_)
- (casesensitive).
- <operand-list> is a sequence of operators seperated by commas
- other than the tabs and crs, no white space is allowed.
-
- <instruction> (and appropriate operands are:
-
- MOVE <value>,<register> (set <register> to <value>)
- ADD <value1>,<value2>,<register> (set <register> to <value1>+<value2>)
- SUB <value1>,<value2>,<register> (set <register> to <value1>-<value2>)
- JMP <label> (jump to line labeled with <label>)
- JEQ <value1>,<value2>,<label> (jump to <label> if <value1> = <value2>)
- JLE <value1>,<value2>,<label> (jump to <label> if <value1> <= <value2>)
- JSR <label> (jump to subroutine at <label>)
- RTS (return from subroutine)
- PUSH <value> (push value on to stack)
- POP <register> (pop value from stack)
-
- <register> is a single uppercase letter in the range A..Z
- <number> is an optional minus sign followed by decimal digits
- <value> is a <register> or a <number>
-
- Note that the data stack and subroutine stack are independent stacks. A RTS is
- used to stop the program (that is, consider that you have JSRed to the initial
- line of the source handle). For example:
-
- PUSH 10
- JSR setA
- JSE setB
- RTS
- setA:
- POP A
- RTS
- setB: MOVE A,B
- RTS
-
- Interpret takes the source handle and JSRs to it, presetting the registers
- according to the register array. When the code returns, the register array is
- set to the final value of all the registers. Both subroutine and data stacks
- should be large (at least 1000 entries each).
- */
-
- #include "Solution.h"
-
- // Fill in your solution and then submit this folder
-
- // Team Name: #5
-
- #include <string.h>
- #include <stdio.h>
-
- const char* CharInLine(const char* src, char c)
- {
- for (; *src != 0x0D; src++)
- if (*src == c)
- return src;
- return nil;
- }
-
- const char* FindOperand(const char*& src, char delimiter)
- {
- const char* end;
- for (end = src;*end != delimiter; end++);
- char* result = new char[end - src + 1];
- memcpy(result, src, end - src);
- result[end - src] = 0;
- src = end + 1;
- return result;
- }
-
- SInt32 GetOperandValue(const char* op, RegisterArray result)
- {
- if (*op >= 'A' && *op <= 'Z')
- return result[*op - 'A'];
- SInt32 val;
- sscanf(op, "%ld", &val);
- return val;
- }
-
- const char* FindLabel(const char* src, const char* srcEnd, const char* label)
- {
- const char* line = src;
- while (line < srcEnd)
- {
- const char* eol;
- for (eol = line; *eol!= 0x0D; eol++);
- if (!eol)
- eol = srcEnd;
- if (strncmp(line, label, strlen(label)) == 0)
- return line;
- line = eol + 1;
- }
- return nil;
- }
-
- pascal void Interpret( Handle source, RegisterArray result )
- {
- HLockHi(source);
- UInt32 length = GetHandleSize(source);
- const char* src = *source;
- const char* eof = src + length;
- const char* line = src;
-
- const char* operand1 = nil;
- const char* operand2 = nil;
- const char* operand3 = nil;
-
- const char* procStackStorage[1001];
- const char** procStack = procStackStorage;
-
- SInt32 dataStackStorage[1001];
- SInt32* dataStack = dataStackStorage;
-
- while (1)
- {
- delete [] operand1;
- delete [] operand2;
- delete [] operand3;
- const char* eol;
- for (eol = line; *eol!= 0x0D; eol++);
- // skip label and tab, if any.
- const char* currentInstruction = CharInLine(line, 0x09) + 1;
- if (!currentInstruction)
- return;
-
- if (strncmp(currentInstruction, "MOV", 3) == 0)
- {
- // MOVE <value>,<register> (set <register> to <value>)
- line = CharInLine(currentInstruction, 0x09) + 1;
- if (!line)
- return;
- operand1 = FindOperand(line, ',');
- operand2 = FindOperand(line, 0xD);
- result[*operand2 - 'A'] = GetOperandValue(operand1, result);
- }
- else if (strncmp(currentInstruction, "ADD", 3) == 0)
- {
- //ADD <value1>,<value2>,<register> (set <register> to <value1>+<value2>)
- line = CharInLine(currentInstruction, 0x09) + 1;
- if (!line)
- return;
- operand1 = FindOperand(line, ',');
- operand2 = FindOperand(line, ',');
- operand3 = FindOperand(line, 0xD);
- result[*operand3 - 'A'] = GetOperandValue(operand1, result) + GetOperandValue(operand2, result);
- }
- else if (strncmp(currentInstruction, "SUB", 3) == 0)
- {
- //SUB <value1>,<value2>,<register> (set <register> to <value1>-<value2>)
- line = CharInLine(currentInstruction, 0x09) + 1;
- if (!line)
- return;
- operand1 = FindOperand(line, ',');
- operand2 = FindOperand(line, ',');
- operand3 = FindOperand(line, 0xD);
- result[*operand3 - 'A'] = GetOperandValue(operand1, result) - GetOperandValue(operand2, result);
- }
- else if (strncmp(currentInstruction, "JMP", 3) == 0)
- {
- //JMP <label> (jump to line labeled with <label>)
- line = CharInLine(currentInstruction, 0x09) + 1;
- if (!line)
- return;
- operand1 = FindOperand(line, 0xD);
- line = FindLabel(line, eof, operand1);
- continue;
- }
- else if (strncmp(currentInstruction, "JEQ", 3) == 0)
- {
- //JEQ <value1>,<value2>,<label> (jump to <label> if <value1> = <value2>)
- line = CharInLine(currentInstruction, 0x09) + 1;
- if (!line)
- return;
- operand1 = FindOperand(line, ',');
- operand2 = FindOperand(line, ',');
- operand3 = FindOperand(line, 0xD);
- if (GetOperandValue(operand1, result) == GetOperandValue(operand2, result))
- {
- line = FindLabel(line, eof, operand3);
- continue;
- }
- }
- else if (strncmp(currentInstruction, "JLE", 3) == 0)
- {
- //JLE <value1>,<value2>,<label> (jump to <label> if <value1> <= <value2>)
- operand1 = FindOperand(line, ',');
- operand2 = FindOperand(line, ',');
- operand3 = FindOperand(line, 0xD);
- if (GetOperandValue(operand1, result) <= GetOperandValue(operand2, result))
- {
- line = FindLabel(line, eof, operand3);
- continue;
- }
- }
- else if (strncmp(currentInstruction, "JSR", 3) == 0)
- {
- //JSR <label> (jump to subroutine at <label>)
- line = CharInLine(currentInstruction, 0x09) + 1;
- if (!line)
- return;
- operand1 = FindOperand(line, 0xD);
- *procStack++ = eol + 1;
- line = FindLabel(src, eof, operand1);
- continue;
- }
- else if (strncmp(currentInstruction, "RTS", 3) == 0)
- {
- //RTS (return from subroutine)
- if (procStack > procStackStorage)
- {
- line = *--procStack;
- continue;
- }
- return;
- }
- else if (strncmp(currentInstruction, "PUS", 3) == 0)
- {
- //PUSH <value> (push value on to stack)
- line = CharInLine(currentInstruction, 0x09) + 1;
- if (!line)
- return;
- operand1 = FindOperand(line, 0xD);
- *dataStack++ = GetOperandValue(operand1, result);
- }
- else if (strncmp(currentInstruction, "POP", 3) == 0)
- {
- //POP <register> (pop value from stack)
- line = CharInLine(currentInstruction, 0x09) + 1;
- if (!line)
- return;
- operand1 = FindOperand(line, 0xD);
- result[*operand1 - 'A'] = *--dataStack;
- }
- line = eol + 1;
- }
- }
-